package org.jradweb.tools.generator.maven;

import static org.unitils.thirdparty.org.apache.commons.dbutils.DbUtils.closeQuietly;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;
import java.util.Set;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.unitils.core.ModulesRepository;
import org.unitils.core.Unitils;
import org.unitils.core.UnitilsException;
import org.unitils.database.DatabaseModule;

/**
 * for execute database script that init database
 * 
 * @goal createDB
 * @phase process-test-resources
 */
public class CreateDB extends BaseMojo {

	private static String PROPERTY_DISABLE_CONSTRAINTS = "dbMaintainer.disableConstraints.enabled";
	private static String PROPERTY_POJECT_CONFIGURATION_FILE_NAME = "project.configuration.file.name";
	private static String PROPERTY_SCHEMA_NAME = "database.schemaNames";

	public static final String PROPKEY_DATASOURCE_DRIVERCLASSNAME = "database.driverClassName";

	/* Property key of the datasource url */
	public static final String PROPKEY_DATASOURCE_URL = "database.url";

	/* Property key of the datasource connect username */
	public static final String PROPKEY_DATASOURCE_USERNAME = "database.userName";

	/* Property key of the datasource connect password */
	public static final String PROPKEY_DATASOURCE_PASSWORD = "database.password";

	@Override
	protected void doExecute() throws MojoExecutionException,
			MojoFailureException {
		String clear = System.getProperty("clear") != null ? System
				.getProperty("clear") : "false";
		String update = System.getProperty("update") != null ? System
				.getProperty("update") : "true";

		Properties props = new Properties();
		try {
			InputStream is1 = Thread.currentThread().getContextClassLoader()
					.getResourceAsStream("unitils-default.properties");
			InputStream is2 = Thread.currentThread().getContextClassLoader()
					.getResourceAsStream("unitils.properties");
			InputStream is3 = Thread.currentThread().getContextClassLoader()
					.getResourceAsStream("my-unitils.properties");
			props.load(is1);
			props.load(is2);
			props.load(is3);

			String projectFile = props
					.getProperty(PROPERTY_POJECT_CONFIGURATION_FILE_NAME);
			if (projectFile != null) {
				String fullPath = this.baseDir + "/src/main/config/"
						+ projectFile + ".properties";
				File pFile = new File(fullPath);
				if (pFile.exists() && pFile.isFile()) {
					InputStream pis = new FileInputStream(pFile);
					props.load(pis);
				}
			}

			props.setProperty(PROPERTY_DISABLE_CONSTRAINTS, "false");
			Set<Object> keys = props.keySet();
			for (Object key : keys) {
				System.out.println(key + " = "
						+ props.getProperty((String) key));
			}
		} catch (IOException e) {
			throw new MojoExecutionException(e.getMessage());
		}

		String schemaName = props.getProperty(PROPERTY_SCHEMA_NAME);

		
		// List<Module> modules=mr.getModules();
		// for(Module module:modules){
		// System.out.println(module.getClass());
		// }
		DataSource ds =this.getDataSource(props);

		if (clear.equals("true") && schemaName != null) {
			System.out.println("droping database " + schemaName + "...");
			this.executeUpdate("drop database if exists " + schemaName, ds);
		}
		System.out.println("createing database " + schemaName + "...");
		this.executeUpdate("create database if not exists " + schemaName
				+ " default character set utf8", ds);
		
		Unitils unitils = new Unitils();
		unitils.init(props);
		ModulesRepository mr = unitils.getModulesRepository();
		DatabaseModule dbm = mr.getModuleOfType(DatabaseModule.class);
		if (update.equals("true")) {
			System.out.println("udpating database...");
			dbm.updateDatabase();
		}
	}

	private DataSource getDataSource(Properties props) {
		String driverClassName = props
				.getProperty(PROPKEY_DATASOURCE_DRIVERCLASSNAME);
		String databaseUrl = "jdbc:mysql://localhost/?characterEncoding=UTF8";
		String userName = props.getProperty(PROPKEY_DATASOURCE_USERNAME);
		String password = props.getProperty(PROPKEY_DATASOURCE_PASSWORD);
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName(driverClassName);
		dataSource.setUsername(userName);
		dataSource.setPassword(password);
		dataSource.setUrl(databaseUrl);
		return dataSource;
	}

	public int executeUpdate(String sql, DataSource dataSource) {

		Connection connection = null;
		Statement statement = null;
		try {
			connection = dataSource.getConnection();
			statement = connection.createStatement();
			return statement.executeUpdate(sql);

		} catch (Exception e) {
			throw new UnitilsException(
					"Error while performing database update: " + sql, e);
		} finally {
			closeQuietly(connection, statement, null);
		}
	}

}
